#include<iostream>
using namespace std;
#include<string>
#include<unistd.h>
#include<sys/types.h>
#include<signal.h>

void PrintPending(sigset_t& pending)
{
    for (int i = 31; i >= 1; i--)
    {
        if (sigismember(&pending, i))
        {
            cout << "1";
        }
        else
        {
            cout << "0";
        }
    }
    cout << endl << endl;
}

//信号捕捉
void handler(int signo)
{
    cout << "catch a signo: " << signo << endl;
}

int main()
{
    signal(2, handler);

    //先对二号信号进行屏蔽
    sigset_t bset, oset;  //先定义两个信号位图变量。这两个变量创建出来后要进行清空， 但是不能直接赋值，这里用到了系统调用
    sigemptyset(&bset);   //对信号位图做清空。 
    sigemptyset(&oset);   //对信号位图做清空。 


    sigaddset(&bset, 2); //给信号位图添加信号位。 但是这里只是将我们的自己创建的信号位图变量弄成了我们想要的bloc信号位图。 但是
    //这个位图需要被设置进入系统的block表里面， 才能真正将我们的信号屏蔽。 
    //而如何设置， 就用到sigprocmask调用
    sigprocmask(SIG_SETMASK, &bset, &oset);



    //重复打印当前进程的pending； 一串零
    sigset_t pending;
    int cnt = 0;

    while (true)
    {
        int n = sigpending(&pending); //将pending位图里面的东西带出来。 
        //2.2
        if (n < 0) continue;

        PrintPending(pending);
        cnt++;
        sleep(1);
        //解除屏蔽, 2号本来被屏蔽， 现在解除2号屏蔽
        if (cnt == 20) //问题是当cnt == 20的时候， 这个进程直接终止了。 这是因为不管我们是阻塞还是不阻塞。 
        //执行的都是默认动作， 如果我们对2号信号进行捕捉， 那么这个进程的2号信号到底是不是阻塞， 都会执行自定义动作。 
        {
            cout << "unblock 2 signal" << endl;
            sigprocmask(SIG_SETMASK, &oset, nullptr); //我们已经把2号信号解除屏蔽了  
        }
        //
    }

    //发送我们的2号新号。一串零， 但是第二个比特位有一个1

    return 0;
}//
